package net.deuce.perf;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Pointcut;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

@Aspect
public class LoggingAspectBean implements MethodBeforeAdvice, AfterReturningAdvice {

    private Log log = LogFactory.getLog(getClass());

    @Pointcut("execution(* net.deuce.perf.*.*(..))")
    public void methodInvocation() {
    }

    /**
     * Log method entry.
     *
     * @param joinPoint
     */
    @Before("methodInvocation()")
    public void logEntry(final JoinPoint joinPoint)
    {
        System.out.println("Entering method " + joinPoint.getSignature().getName() + "...");
        if (log.isDebugEnabled()) {
           log.debug("Entering method " + joinPoint.getSignature().getName() + "...");
        }
    }

    /**
     * Log method exit.
     *
     * @param joinPoint
     */
    @After("methodInvocation()")
    public void logExit(final JoinPoint joinPoint)
    {
        System.out.println("Exiting method " + joinPoint.getSignature().getName() + ".");
        if (log.isDebugEnabled()) {
           log.debug("Exiting method " + joinPoint.getSignature().getName() + ".");
        }
    }

    /**
     * Log method exit after returning.
     *
     * @param joinPoint
     */
    @AfterReturning("methodInvocation()")
    public void logExitAfterReturn(final JoinPoint joinPoint)
    {
        System.out.println(  "Exiting method (after return) " + joinPoint.getSignature().getName() + ".");
        if (log.isDebugEnabled()) {
           log.debug(  "Exiting method (after return) " + joinPoint.getSignature().getName() + ".");
        }
    }

    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("Entering method " + method.getName() + "...");
    }

    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("Exiting method " + method.getName());
    }
}
